Amazon Athena で CloudFront のアクセスログを集計する
こんにちは、菊池です。
これまでのエントリで、ELBのログをAmazon Athenaで分析する方法を紹介しました。
- Amazon Athena RegexSerDe を利用して CLB ログ / Apache Web のアクセスログを探索する
- Amazon Athena RegexSerDe を利用して ALB ログを探索する
今回は、CloudFrontのアクセスログをAmazon Athenaで分析してみます。
CloudFront とは
Amazon CloudFrontは、AWSが提供するコンテンツ配信サービス(CDN)です。ユーザからのアクセスを、世界中にあるエッジサーバを経由するよう誘導することで、高速なアクセスを提供します。また、エッジサーバにコンテンツをキャッシュすることで、オリジンサーバの負荷を低減することもできます。
CloudFrontのアクセスログ
CloudFrontのアクセスログは、ディストリビューションごとに指定したS3のバケットに保存されます。
ウェブディストリビューションとRTMPディストリビューションでログファイルの形式は異なりますので、今回はウェブシストリビューションを対象にします。
テーブル定義
ログファイルのフィールドを、ドキュメントを参考に以下の様にテーブルのカラムにマッピングします。
フィールド | 説明 |
---|---|
request_date | イベントが発生した日付。yyyy-mm-dd形式。UTC。 |
request_time | CloudFrontがリクエストへの対応を完了した時刻(UTC)。 |
x_edge_location | リクエストを処理したエッジロケーション。3文字コードと割り当てられた数字で識別される。 |
sc_bytes | CloudFront がリクエストに応答してビューワーに渡したデータの総バイト数 |
client_ip | リクエストを送信したクライアントの IP アドレス。 |
cs_method | リクエスト時のHTTPメソッド。 |
cs_host | CloudFront ディストリビューションのドメイン名。 |
cs_uri_stem | パスおよびオブジェクトを識別する URI 。 |
sc_status | CloudFrontが応答したHTTP ステータスコード。応答前にクライアントが切断した場合は"000"を記録。 |
cs_referer | リクエスト元のドメインの名前。 |
user_agent | リクエスト内の User-Agent ヘッダーの値。 |
uri_query | URI のクエリ文字列の部分 (ある場合)。ない場合には"-"を記録。 |
cookie | リクエスト内の Cookie ヘッダー。ない場合には"-"を記録。 |
x_edge_result_type | エッジロケーションへのCloudFrontのレスポンスの分類。例えば以下のようなものがある。
|
x_edge_request_id | 要求を一意に識別する文字列。 |
x_host_header | ビューワーによってこのリクエストの Host ヘッダーに追加された値。 |
cs_protocol | リクエストのプロトコル。httpまたはhttps |
cs_bytes | リクエストに組み込まれたデータのバイト数 |
time_taken | CloudFrontエッジサーバがリクエストを受け取ってから、レスポンスの最終バイトをエッジサーバーの出力キューに書き込むまでの秒数。 |
x_forwarded_for | ビューワーがリクエストを送るのに HTTPプロキシやロードバランサーを使った場合、client_ipの値は、プロキシあるいはロードバランサーの IP アドレスとなる。その場合のリクエスト元のビューワーの IP アドレス。 |
ssl_protocol | cs_protocolがhttpsの場合のSSLプロトコル。 |
ssl_cipher | cs_protocolがhttpsの場合のSSL 暗号。 |
x_edge_response_result_type | CloudFront がレスポンスをビューワーに返す直前に行った分類。x_edge_result_typeも参照。 |
cs_protocol_version | リクエストで指定した HTTP バージョン。 |
これらを順にカラムとして定義します。Amazon Athena は、ログが複数のファイルの場合でも、同じフォルダに配置することで同じテーブル内のデータとしてクエリーを実行できます。
CREATE EXTERNAL TABLE IF NOT EXISTS cf_log ( request_date STRING, request_time STRING, x_edge_location STRING, sc_bytes INT, client_ip STRING, cs_method STRING, cs_host STRING, cs_uri_stem STRING, sc_status STRING, cs_referer STRING, user_agent STRING, uri_query STRING, cookie STRING, x_edge_result_type STRING, x_edge_request_id STRING, x_host_header STRING, cs_protocol STRING, cs_bytes INT, time_taken DECIMAL(8,3), x_forwarded_for STRING, ssl_protocol STRING, ssl_cipher STRING, x_edge_response_result_type STRING, cs_protocol_version STRING ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '\t', 'input.regex' = '\t' ) LOCATION 's3://LOG_BUCKET_NAME/cf/' TBLPROPERTIES ('has_encrypted_data'='false');
上記のDDLをテンプレートとして利用する場合、LOCATION
に指定するクエリ対象のロフファイルを保存している S3バケット/フォルダ名を変更するだけで、再利用できます。
全てのレコードの全てのカラムデータが参照できることが確認できます。
SELECT * FROM sampledb."cf_log" limit 10;
CloudFront アクセスログの集計
実際にCloudFrontのアクセスログを集計する例を、いくつか紹介します。
エッジロケーションごとのアクセス数を集計
どの地域からのアクセス数が多いか、調べてみるのに使えるかと思います。
SELECT x_edge_location, count(*) AS num FROM cf_log WHERE request_date = '2017-08-15' GROUP BY 1 ORDER BY 1;
クライアントIPごとにアクセス数を集計
クライアントのIPアドレスごとのアクセス数を集計します。BotやF5アタックなど、不適切なアクセスを仕掛けてくるIPを特定し、AWS WAFで遮断するなどの対応を想定しています。
SELECT client_ip, x_edge_location, count(*) AS num FROM cf_log WHERE request_date = '2017-08-15' GROUP BY 1,2 ORDER BY 1;
パスごとにキャッシュ有無によるレスポンス時間を集計
アクセス先のパスごとに、平均のレスポンス時間を集計しています。キャッシュの状態により、ユーザへどの程度のレスポンス時間でサービスできているか確認できます。
SELECT cs_uri_stem, x_edge_result_type, avg(time_taken) AS num FROM cf_log WHERE request_date = '2017-08-15' GROUP BY 1,2 ORDER BY 1;
最後に
以上です。
ELB(CLB/ALB)に続き、CloudFrontのアクセスログをAthenaで集計する手順を紹介しました。AWSでは、S3にログを出力するサービスが多いですが、Athenaを使うことでカジュアルに分析することができます。